/*
 * GalilGiancarlo.cpp
 *
 *  Created on: 23-08-2013
 *      Author: Krzychu
 */

#include "GalilGiancarlo.h"

#include "Config.h"

GalilGiancarlo::GalilGiancarlo()
{

}

GalilGiancarlo::~GalilGiancarlo()
{

}

std::string GalilGiancarlo::getName()
{
	return "Galil Giancarlo";
}

searchResult GalilGiancarlo::execute(std::string text, std::string pattern)
{
	searchResult result;
	result.iterationsTaken = 0;

	int textSize = text.size();
	int patternSize = pattern.size();
    int i, j, k, ell, last, nd;
	int h[patternSize], next[patternSize], shift[patternSize];
	char heavy;

	for (ell = 0; pattern[ell] == pattern[ell + 1]; ell++);
	if (ell == patternSize - 1)
	{
		/* Searching for a power of a single character */
		for (j = ell = 0; j < textSize; ++j)
			if (pattern[0] == text[j])
			{
				++ell;
				if (ell >= patternSize)
				{
					result.positionsFound.push_back(j - patternSize + 1);
					if (Config::getInstance()->getFindOneOccurence())
					{
						return result;
					}
				}
			}
			else
			{
				ell = 0;
			}
	}
	else
	{
		/* Preprocessing */
		nd = preColussi(pattern, h, next, shift);

		/* Searching */
		i = j = heavy = 0;
		last = -1;
		while (j <= textSize - patternSize)
		{
			result.iterationsTaken++;
			if (heavy && i == 0)
			{
				k = last - j + 1;
				while (pattern[0] == text[j + k])
				{
					k++;
				}
				if (k <= ell || pattern[ell + 1] != text[j + k])
				{
					i = 0;
					j += (k + 1);
					last = j - 1;
				}
				else
				{
					i = 1;
					last = j + k;
					j = last - (ell + 1);
				}
				heavy = 0;
			}
			else
			{
				while (i < patternSize && last < j + h[i] && pattern[h[i]] == text[j + h[i]])
				{
					++i;
				}
				if (i >= patternSize || last >= j + h[i])
				{
					result.positionsFound.push_back(j);
					if (Config::getInstance()->getFindOneOccurence())
					{
						return result;
					}
					i = patternSize;
				}
				if (i > nd)
				{
					last = j + patternSize - 1;
				}
				j += shift[i];
				i = next[i];
			}
			heavy = (j > last ? 0 : 1);
		}
	}


	return result;
}

